import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { API_CONFIG } from './config'

// 请求响应接口
export interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
  success: boolean
}

// 扩展 Error 类型
interface CustomError extends Error {
  code?: number
  originalError?: any
}

// 请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
  retry?: number
  retryDelay?: number
  showLoading?: boolean
  showError?: boolean
}

class HttpRequest {
  private instance: AxiosInstance
  private pendingRequests: Map<string, AbortController> = new Map()

  constructor() {
    // 创建 axios 实例
    this.instance = axios.create({
      baseURL: API_CONFIG.BASE_URL,
      timeout: API_CONFIG.TIMEOUT,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    // 设置请求拦截器
    this.setupRequestInterceptors()
    
    // 设置响应拦截器
    this.setupResponseInterceptors()
  }

  // 设置请求拦截器
  private setupRequestInterceptors() {
    this.instance.interceptors.request.use(
      (config) => {
        // 添加请求唯一标识
        const requestKey = this.getRequestKey(config)
        
        // 取消重复请求
        if (this.pendingRequests.has(requestKey)) {
          this.pendingRequests.get(requestKey)?.abort()
        }
        
        // 创建新的 AbortController
        const controller = new AbortController()
        config.signal = controller.signal
        this.pendingRequests.set(requestKey, controller)

        // 添加认证 token
        const token = localStorage.getItem('access_token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 添加时间戳防止缓存
        if (config.method === 'get') {
          config.params = {
            ...config.params,
            _t: Date.now(),
          }
        }

        console.log(`🚀 请求发送: ${config.method?.toUpperCase()} ${config.url}`, config)
        return config
      },
      (error) => {
        console.error('❌ 请求配置错误:', error)
        return Promise.reject(error)
      }
    )
  }

  // 设置响应拦截器
  private setupResponseInterceptors() {
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        // 移除已完成的请求
        const requestKey = this.getRequestKey(response.config)
        this.pendingRequests.delete(requestKey)

        console.log(`✅ 请求成功: ${response.config.method?.toUpperCase()} ${response.config.url}`, response.data)

        // 统一处理响应数据
        // Check if response is a blob (file download)
        if (response.data instanceof Blob) {
          // For file downloads, we consider HTTP status 200 as success
          if (response.status >= 200 && response.status < 300) {
              return response
          } else {
              // Try to read error message from blob (if server sends error as file)
              const error = new Error('文件下载失败') as CustomError
              error.code = response.status
              return Promise.reject(error)
          }
        } 
        // Handle normal JSON responses
        else {
          const { data } = response
          
          if (data.success === true || data.code <= 299) {
              return response
          } else {
              // Business error handling
              const error = new Error(data.message || '请求失败') as CustomError
              error.code = data.code
              return Promise.reject(error)
          }
        }
      },
      async (error: AxiosError) => {
        const config = error.config as RequestConfig
        
        // 移除失败的请求
        if (config) {
          const requestKey = this.getRequestKey(config)
          this.pendingRequests.delete(requestKey)
        }

        console.error(`❌ 请求失败: ${config?.method?.toUpperCase()} ${config?.url}`, error)

        // 请求重试逻辑
        if (config && this.shouldRetry(error, config)) {
          return this.retryRequest(config)
        }

        // 统一错误处理
        return this.handleError(error)
      }
    )
  }

  // 生成请求唯一标识
  private getRequestKey(config: AxiosRequestConfig): string {
    return `${config.method}_${config.url}_${JSON.stringify(config.params)}_${JSON.stringify(config.data)}`
  }

  // 判断是否需要重试
  private shouldRetry(error: AxiosError, config: RequestConfig): boolean {
    const retryCount = config.retry ?? API_CONFIG.RETRY_COUNT
    const currentRetry = (config as any).__retryCount || 0
    
    // 网络错误或超时错误才重试
    const shouldRetry = (
      error.code === 'ECONNABORTED' || 
      error.code === 'NETWORK_ERROR' ||
      (error.response?.status && error.response.status >= 500)
    )
    
    return shouldRetry && currentRetry < retryCount
  }

  // 重试请求
  private async retryRequest(config: RequestConfig): Promise<any> {
    const currentRetry = (config as any).__retryCount || 0
    const retryDelay = config.retryDelay ?? API_CONFIG.RETRY_DELAY
    
    ;(config as any).__retryCount = currentRetry + 1
    
    console.log(`🔄 请求重试 (${currentRetry + 1}/${config.retry ?? API_CONFIG.RETRY_COUNT}): ${config.url}`)
    
    // 延迟重试
    await new Promise(resolve => setTimeout(resolve, retryDelay))
    
    return this.instance.request(config)
  }

  // 统一错误处理
  private handleError(error: AxiosError): Promise<never> {
    let message = '请求失败'
    
    if (error.response) {
      // 服务器响应错误
      const status = error.response.status
      switch (status) {
        case 400:
          message = '请求参数错误'
          break
        case 401:
          message = '未授权，请重新登录'
          // 清除 token 并跳转到登录页
          localStorage.removeItem('access_token')
          window.location.href = '/login'
          break
        case 403:
          message = '拒绝访问'
          break
        case 404:
          message = '请求资源不存在'
          break
        case 500:
          message = '服务器内部错误'
          break
        default:
          message = `请求失败 (${status})`
      }
    } else if (error.request) {
      // 网络错误
      message = '网络连接失败，请检查网络'
    } else {
      // 其他错误
      message = error.message || '未知错误'
    }

    const customError = new Error(message) as CustomError
    customError.originalError = error
    
    return Promise.reject(customError)
  }

  // GET 请求
  get<T = any>(url: string, params?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.instance.get(url, { params, ...config }).then(response => response.data)
  }

  // POST 请求
  post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.instance.post(url, data, config).then(response => response.data)
  }

  // PUT 请求
  put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.instance.put(url, data, config).then(response => response.data)
  }

  // DELETE 请求
  delete<T = any>(url: string, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.instance.delete(url, config).then(response => response.data)
  }

  // PATCH 请求
  patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.instance.patch(url, data, config).then(response => response.data)
  }

  // 上传文件
  upload<T = any>(url: string, file: File, config?: RequestConfig): Promise<ApiResponse<T>> {
    const formData = new FormData()
    formData.append('file', file)
    
    return this.instance.post(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      ...config,
    }).then(response => response.data)
  }

  // 下载文件
  download(url: string, filename?: string, config?: RequestConfig): Promise<void> {
    return this.instance.get(url, {
      responseType: 'blob',
      ...config,
    }).then((response) => {
      console.log('下载响应头:', response.headers)
      console.log('响应数据类型:', response.data.type)
      
      // 获取 Content-Type
      const contentType = response.headers['content-type'] || response.data.type
      console.log('Content-Type:', contentType)
      
      // 根据内容类型创建正确的 Blob
      let blob: Blob
      if (contentType && contentType.includes('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) {
        // Excel 文件
        blob = new Blob([response.data], { 
          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 
        })
      } else if (contentType && contentType.includes('application/vnd.ms-excel')) {
        // 旧版 Excel 文件
        blob = new Blob([response.data], { 
          type: 'application/vnd.ms-excel' 
        })
      } else {
        // 默认使用响应的 Content-Type
        blob = new Blob([response.data], { type: contentType })
      }
      
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      
      // 优先使用后端返回的文件名
      let finalFilename = filename || 'download.xlsx'
      
      // 从 Content-Disposition 头中提取文件名
      const contentDisposition = response.headers['content-disposition']
      if (contentDisposition) {
        console.log('Content-Disposition:', contentDisposition)
        
        // 优先处理 UTF-8 编码的文件名 filename*=UTF-8''encoded_filename
        const utf8Match = contentDisposition.match(/filename\*=UTF-8''(.+?)(?:;|$)/)
        if (utf8Match) {
          try {
            finalFilename = decodeURIComponent(utf8Match[1])
            console.log('解析UTF-8文件名:', finalFilename)
          } catch (e) {
            console.warn('UTF-8文件名解码失败:', e)
          }
        } else {
          // 处理普通的 filename="filename" 或 filename=filename
          const normalMatch = contentDisposition.match(/filename="([^"]+)"|filename=([^;]+)/)
          if (normalMatch) {
            finalFilename = normalMatch[1] || normalMatch[2]
            console.log('解析普通文件名:', finalFilename)
          }
        }
      }
      
      // 确保文件名有正确的扩展名
      if (finalFilename && !finalFilename.includes('.')) {
        if (contentType && contentType.includes('spreadsheetml.sheet')) {
          finalFilename += '.xlsx'
        } else if (contentType && contentType.includes('ms-excel')) {
          finalFilename += '.xls'
        }
      }
      
      link.download = finalFilename
      console.log('最终下载文件名:', finalFilename)
      console.log('最终 Blob 类型:', blob.type)
      
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
    })
  }

  // 取消所有请求
  cancelAllRequests() {
    this.pendingRequests.forEach((controller) => {
      controller.abort()
    })
    this.pendingRequests.clear()
  }

  // 取消指定请求
  cancelRequest(config: AxiosRequestConfig) {
    const requestKey = this.getRequestKey(config)
    const controller = this.pendingRequests.get(requestKey)
    if (controller) {
      controller.abort()
      this.pendingRequests.delete(requestKey)
    }
  }
}

// 创建请求实例
const request = new HttpRequest()

export default request